#include "graphics.opengl/program.h"
#include "graphics.opengl/shader.h"

namespace dw
{
	namespace graphics
	{
		namespace opengl
		{

			Program::Program() : _glId(0)
			{
				_glId = glCreateProgramObjectARB();
			}

			Program::Program(const std::string& vertexShader, const std::string& fragmentShader)
			{
				Shader* vsh;
				Shader* fsh;
				
				_glId = glCreateProgramObjectARB();
				vsh = new Shader(Shader::VERTEX_SHADER);
				fsh = new Shader(Shader::FRAGMENT_SHADER);
				vsh->loadFromFile(vertexShader);
				fsh->loadFromFile(fragmentShader);
				attachShader(vsh);
				attachShader(fsh);
			}

			Program::~Program()
			{
				glDeleteObjectARB(_glId);
			}

			void Program::attachShader(dw::graphics::Shader* shader)
			{
				glAttachObjectARB(_glId, static_cast< Shader* >(shader)->getGLId());
				_shaders.insert(shader);
			}

			void Program::detachShader(dw::graphics::Shader* shader)
			{
				glDetachObjectARB(_glId, static_cast< Shader* >(shader)->getGLId());
				_shaders.erase(shader);
			}

			void Program::link()
			{
				int linked;				

				glLinkProgramARB(_glId);
				glGetObjectParameterivARB(_glId, GL_OBJECT_LINK_STATUS_ARB, &linked);
				//if (!linked)
				{
					int maxLength;
					char* infoLog;

					glGetObjectParameterivARB(_glId, GL_OBJECT_INFO_LOG_LENGTH_ARB, &maxLength);
					infoLog = new char[maxLength];
					glGetInfoLogARB(_glId, maxLength, &maxLength, infoLog);
					std::string tmp = infoLog;
					delete [] infoLog;

					// DW_INFO << infoLog << std::endl;
				}
			}

			void Program::build()
			{
				// DW_INFO << "----------------- Build started ------------------" << std::endl;
				// DW_INFO << "Compiling..." << std::endl;
				for (ShaderIterator iter = _shaders.begin(); iter != _shaders.end(); ++iter)
					(*iter)->compile();
				// DW_INFO << "Linking..." << std::endl;
				link();
				// DW_INFO << "---------------------- Done ----------------------" << std::endl;
			}
		
		} // namespace opengl
	} // namespace graphics
} // namespace dw

